﻿using System;
using System.Net;
using System.IO;
using System.Linq;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.ComponentModel;
using System.Runtime.CompilerServices;
using Windows.ApplicationModel.Resources.Core;
using Windows.Foundation;
using Windows.Foundation.Collections;
using Windows.UI.Xaml;
using Windows.UI.Xaml.Controls;
using Windows.UI.Xaml.Controls.Primitives;
using Windows.UI.Xaml.Data;
using Windows.UI.Xaml.Media;
using Windows.UI.Xaml.Media.Imaging;
using System.Collections.Specialized;
using TR1app.DataModel;
using Windows.Data.Html;
using System.Net.Http;
using System.Threading.Tasks;
using HtmlAgilityPack;

// The data model defined by this file serves as a representative example of a strongly-typed
// model that supports notification when members are added, removed, or modified.  The property
// names chosen coincide with data bindings in the standard item templates.
//
// Applications may use this model as a starting point and build on it, or discard it entirely and
// replace it with something appropriate to their needs.

namespace TR1app.Data
{
    /// <summary>
    /// Base class for <see cref="RSSDataItem"/> and <see cref="SampleDataGroup"/> that
    /// defines properties common to both.
    /// </summary>
    [Windows.Foundation.Metadata.WebHostHidden]
    public abstract class RSSDataCommon : TR1app.Common.BindableBase
    {
        private static Uri _baseUri = new Uri("ms-appx:///");

        public RSSDataCommon(String uniqueId, String title, String subtitle, String imagePath, String description)
        {
            this._uniqueId = uniqueId;
            this._title = title;
            this._subtitle = subtitle;
            this._description = description;
            this._imagePath = imagePath;
        }

        private string _uniqueId = string.Empty;
        public string UniqueId
        {
            get { return this._uniqueId; }
            set { this.SetProperty(ref this._uniqueId, value); }
        }

        private string _title = string.Empty;
        public string Title
        {
            get { return this._title; }
            set { this.SetProperty(ref this._title, value); }
        }

        private string _subtitle = string.Empty;
        public string Subtitle
        {
            get { return this._subtitle; }
            set { this.SetProperty(ref this._subtitle, value); }
        }

        private string _description = string.Empty;
        public string Description
        {
            get { return this._description; }
            set { this.SetProperty(ref this._description, value); }
        }

        private string _caption = string.Empty;
        public string Caption
        {
            get { return this._caption; }
            set { this.SetProperty(ref this._caption, value); }
        }

        private ImageSource _image = null;
        private String _imagePath = null;
        public ImageSource Image
        {
            get
            {
                if (this._image == null && this._imagePath != null)
                {
                    this._image = new BitmapImage(new Uri(RSSDataCommon._baseUri, this._imagePath));
                }
                return this._image;
            }

            set
            {
                this._imagePath = null;
                this.SetProperty(ref this._image, value);
            }
        }

        public void SetImage(String path)
        {
            this._image = null;
            this._imagePath = path;
            this.OnPropertyChanged("Image");
        }

        public override string ToString()
        {
            return this.Title;
        }
    }

    /// <summary>
    /// Generic item data model.
    /// </summary>
    public class RSSDataItem : RSSDataCommon
    {
        public RSSDataItem(String uniqueId, String title, String subtitle, String imagePath, String description, Uri contentURL, SampleDataGroup group)
            : base(uniqueId, title, subtitle, imagePath, description)
        {
            this._contentURL = contentURL;
            this._group = group;
        }

        private Uri _contentURL ;
        public Uri ContentURL
        {
            get { return this._contentURL; }
            set { this.SetProperty(ref this._contentURL, value); }
        }

        private string _content = string.Empty;
        public string Content
        {
            get { return this._content; }
            set { this.SetProperty(ref this._content, value); }
        }

        private string _authorInfo = string.Empty;
        public string AuthorInfo
        {
            get { return this._authorInfo; }
            set { this.SetProperty(ref this._authorInfo, value); }
        }

        private string _authorName = string.Empty;
        public string AuthorName
        {
            get { return this._authorName; }
            set { this.SetProperty(ref this._authorName, value); }
        }

        private string _authorImageURL = string.Empty;
        public string AuthorImageURL
        {
            get { return this._authorImageURL; }
            set { this.SetProperty(ref this._authorImageURL, value); }
        }

        private int _commentCount = 0;
        public int  CommentCount
        {
            get { return this._commentCount; }
            set { this.SetProperty(ref this._commentCount, value); }
        }

        private SampleDataGroup _group;
        public SampleDataGroup Group
        {
            get { return this._group; }
            set { this.SetProperty(ref this._group, value); }
        }
    }

    /// <summary>
    /// Generic group data model.
    /// </summary>
    public class SampleDataGroup : RSSDataCommon
    {
        public SampleDataGroup(String uniqueId, String title, String subtitle, String imagePath, String description)
            : base(uniqueId, title, subtitle, imagePath, description)
        {
            Items.CollectionChanged += ItemsCollectionChanged;
        }

        private void ItemsCollectionChanged(object sender, System.Collections.Specialized.NotifyCollectionChangedEventArgs e)
        {
            // Provides a subset of the full items collection to bind to from a GroupedItemsPage
            // for two reasons: GridView will not virtualize large items collections, and it
            // improves the user experience when browsing through groups with large numbers of
            // items.
            //
            // A maximum of 12 items are displayed because it results in filled grid columns
            // whether there are 1, 2, 3, 4, or 6 rows displayed

            switch (e.Action)
            {
                case NotifyCollectionChangedAction.Add:
                    if (e.NewStartingIndex < 12)
                    {
                        TopItems.Insert(e.NewStartingIndex,Items[e.NewStartingIndex]);
                        if (TopItems.Count > 12)
                        {
                            TopItems.RemoveAt(12);
                        }
                    }
                    break;
                case NotifyCollectionChangedAction.Move:
                    if (e.OldStartingIndex < 12 && e.NewStartingIndex < 12)
                    {
                        TopItems.Move(e.OldStartingIndex, e.NewStartingIndex);
                    }
                    else if (e.OldStartingIndex < 12)
                    {
                        TopItems.RemoveAt(e.OldStartingIndex);
                        TopItems.Add(Items[11]);
                    }
                    else if (e.NewStartingIndex < 12)
                    {
                        TopItems.Insert(e.NewStartingIndex, Items[e.NewStartingIndex]);
                        TopItems.RemoveAt(12);
                    }
                    break;
                case NotifyCollectionChangedAction.Remove:
                    if (e.OldStartingIndex < 12)
                    {
                        TopItems.RemoveAt(e.OldStartingIndex);
                        if (Items.Count >= 12)
                        {
                            TopItems.Add(Items[11]);
                        }
                    }
                    break;
                case NotifyCollectionChangedAction.Replace:
                    if (e.OldStartingIndex < 12)
                    {
                        TopItems[e.OldStartingIndex] = Items[e.OldStartingIndex];
                    }
                    break;
                case NotifyCollectionChangedAction.Reset:
                    TopItems.Clear();
                    while (TopItems.Count < Items.Count && TopItems.Count < 12)
                    {
                        TopItems.Add(Items[TopItems.Count]);
                    }
                    break;
            }
        }

        private ObservableCollection<RSSDataItem> _items = new ObservableCollection<RSSDataItem>();
        public ObservableCollection<RSSDataItem> Items
        {
            get { return this._items; }
        }

        private ObservableCollection<RSSDataItem> _topItem = new ObservableCollection<RSSDataItem>();
        public ObservableCollection<RSSDataItem> TopItems
        {
            get {return this._topItem; }
        }
    }

    /// <summary>
    /// Creates a collection of groups and items with hard-coded content.
    /// 
    /// RSSDataSource initializes with placeholder data rather than live production
    /// data so that sample data is provided at both design-time and run-time.
    /// </summary>
    public sealed class RSSDataSource
    {
        private static RSSDataSource _sampleDataSource = new RSSDataSource();

        private ObservableCollection<SampleDataGroup> _allGroups = new ObservableCollection<SampleDataGroup>();
        public ObservableCollection<SampleDataGroup> AllGroups
        {
            get { return this._allGroups; }
        }

        public static IEnumerable<SampleDataGroup> GetGroups(string uniqueId)
        {
            if (!uniqueId.Equals("AllGroups")) throw new ArgumentException("Only 'AllGroups' is supported as a collection of groups");
            
            return _sampleDataSource.AllGroups;
        }

        public static SampleDataGroup GetGroup(string uniqueId)
        {
            // Simple linear search is acceptable for small data sets
            var matches = _sampleDataSource.AllGroups.Where((group) => group.UniqueId.Equals(uniqueId));
            if (matches.Count() == 1) return matches.First();
            return null;
        }

        public static RSSDataItem GetItem(string uniqueId)
        {
            // Simple linear search is acceptable for small data sets
            var matches = _sampleDataSource.AllGroups.SelectMany(group => group.Items).Where((item) => item.UniqueId.Equals(uniqueId));
            if (matches.Count() == 1)
            {
                var match = matches.First();
              //    UpdateContent(match);
                return match;
            }
            return null;
        }


//        public static async Task  UpdateContent(RSSDataItem match)
//        {
//            if (match.Content != null) // if we have already updated the content do not do this again
//            {
//                var webGet = new HtmlWeb();
//                var document = await webGet.LoadFromWebAsync(match.ContentURL.AbsoluteUri);
//                var response = "1";
//                var divTags = document.DocumentNode.Descendants("section");
//                HtmlNode ArticalNode = null;
//                HtmlNode AuthorInfo = null;
//                foreach (var tag in divTags)
//                {
//                    if (tag.Attributes[0] != null && tag.Attributes[0] != null)
//                    {
//                        if (tag.Attributes[0].Value == "main-artical") // contains the Link to the Autor Bio etc
//                            AuthorInfo = tag;
//                        if (tag.Attributes[0].Value == "body")  // this is the actual Atrical text
//                        {
//                            ArticalNode = tag;
//                            response = ArticalNode.InnerHtml;
//                        }
////                        if (tag.Attributes[0].Value == "story-img") // contains the Link to the Autor Bio etc
////                            ImageInfo = tag;
//                        if (tag.Attributes[0].Value == "ad-left")  // this is the Ad that is embeded in the middle of the artical we want to clean out
//                        {
//                            tag.Remove();
//                            response = ArticalNode.InnerHtml;
//                        }
////                        if (tag.Attributes[0].Value == "authors") // contains the Link to the Autor Bio etc
////                            AuthorInfo = tag;
////                        if (tag.Attributes[0].Value == "explore") // contains the Link to the Autor Bio etc
////                            ExploreInfo = tag;
////                        if (tag.Attributes[0].Value == "comments") // contains the Link to the Autor Bio etc
////                            CommentsInfo = tag;

//                    }
//                }
//                match.Content = response; 
///*                foreach (var tag in divTags)
//                {
//                    if (tag.Attributes[0] != null && tag.Attributes[0] != null)
//                    {
//                        if (tag.Attributes[0].Value == "story-meta") // contains the Link to the Autor Bio etc
//                            AuthorInfo = tag;
//                        if (tag.Attributes[0].Value == "mainBody" || tag.Attributes[0].Value == "entry-content")  // this is the actual Atrical text
//                        {
//                            ArticalNode = tag;
//                            match.Content = ArticalNode.InnerText;
//                        }
//                        if (tag.Attributes[0].Value == "articleAd")  // this is the Ad that is embeded in the middle of the artical we want to clean out
//                        {
//                            tag.RemoveAllChildren();
//                            match.Content = ArticalNode.InnerText;
//                        }
//                    }
//                }
//*/            }
//              var x = 2;
//        }

        private static async Task<String> GetContentAsync(Uri UrlString)
        {
            var client = new HttpClient();
            try{
                var response = await client.GetAsync(UrlString);
                var result = await response.Content.ReadAsStringAsync();

                return result;
            }
            catch (Exception)
            {
                return null;
            }
        }

        private static async Task GetBackgroundInfoForContent_Async(RSSDataItem feedItem)
        {
            var webGet = new HtmlWeb();
            var document = await webGet.LoadFromWebAsync(feedItem.ContentURL.AbsoluteUri);
            var SectionTags = document.DocumentNode.Descendants("section");
            HtmlNode ArticalNode = null;
            HtmlNode CommentNode = null;
            HtmlNode AuthorInfoNode = null;
            var response = String.Empty;
            var response2 = String.Empty;

            foreach (var tag in SectionTags)               // Search for Actual content of artical
            {
                if (tag.Attributes[0] != null)
                {
                    if (tag.Attributes[0].Value == "body")  // this is the actual Artical text
                    {
                        ArticalNode = tag;
                        response = ArticalNode.InnerHtml;
                        feedItem.Content = response;
                        response2 = await GetArticalImg(ArticalNode);
                        if(response2.Length != 0)
                            feedItem.SetImage(response2);
                       // break;
                    }
                    if (tag.Attributes[0].Name == "class" && tag.Attributes[0].Value == "comments")  // this is the Comment node
                    {
                        CommentNode = tag;
                        feedItem.CommentCount = GetCommentCount(CommentNode);
                       // break;
                    }
                    if (tag.Attributes[0].Value == "authors")  // this is the actual Artical text
                    {
                        AuthorInfoNode = tag;
                        response = AuthorInfoNode.InnerHtml;
                        feedItem.AuthorInfo = response;
                        feedItem.AuthorImageURL = GetAuthorImg(AuthorInfoNode);
                        feedItem.AuthorName = GetAuthorName(AuthorInfoNode);
                        //break;
                    }
                }
            }
        }
        private static int GetCommentCount(HtmlNode CommentNode)
        {
            var divTags2 = CommentNode.Descendants("span");
            int count = 0;

            foreach (var tag in divTags2)                // Search artical section holding the number of comments
            {
                if (tag.Attributes[0] != null)
                {
                    if (tag.Attributes[0].Value == "number") // look for the Div with the Number reference in it
                    {
                        count = Convert.ToInt16(tag.InnerText);
                        break;
                    }
                }
            }
            return count;
        }
        private static async Task<String> GetArticalImg(HtmlNode ArticalNode)
        {
            String response = String.Empty;
            var divTags = ArticalNode.Descendants("img");

            foreach (var tag in divTags)                // Search for artical content for any image we can use
            {
                if (tag.Attributes[0] != null)
                {
                    response = tag.Attributes["src"].Value;
                    break;
                }
            }
            return response;
        }
        private static String GetAuthorImg(HtmlNode AuthorInfoNode)
        {
            String response = String.Empty;
            var divTags = AuthorInfoNode.Descendants("img");
            response = divTags.First().Attributes["src"].Value;
            //foreach (var tag in divTags)                // Search for artical content for any image we can use
            //{
            //    if (tag.Attributes[0] != null)
            //    {
            //        response = tag.Attributes["src"].Value;
            //        break;
            //    }
            //}
            return response;
        }
        private static String GetAuthorName(HtmlNode AuthorInfoNode)
        {
            String response = String.Empty;
            var divTags = AuthorInfoNode.Descendants("h3");

            response = divTags.First().InnerText;
            //foreach (var tag in divTags)                // Search for artical content for any image we can use
            //{
            //    response = AuthorInfoNode.InnerHtml;
            //}
            return response;
        }

        public RSSDataSource()
        {
           
            FeedDataSource feedDataSource = (FeedDataSource)App.Current.Resources["feedDataSource"];

            String ITEM_CONTENT = String.Format("Item Content: {0}\n\n{0}\n\n{0}\n\n{0}\n\n{0}\n\n{0}\n\n{0}",
                        "Curabitur class aliquam vestibulum nam curae maecenas sed integer cras phasellus suspendisse quisque donec dis praesent accumsan bibendum pellentesque condimentum adipiscing etiam consequat vivamus dictumst aliquam duis convallis scelerisque est parturient ullamcorper aliquet fusce suspendisse nunc hac eleifend amet blandit facilisi condimentum commodo scelerisque faucibus aenean ullamcorper ante mauris dignissim consectetuer nullam lorem vestibulum habitant conubia elementum pellentesque morbi facilisis arcu sollicitudin diam cubilia aptent vestibulum auctor eget dapibus pellentesque inceptos leo egestas interdum nulla consectetuer suspendisse adipiscing pellentesque proin lobortis sollicitudin augue elit mus congue fermentum parturient fringilla euismod feugiat");

            var group1 = new SampleDataGroup("Group-1",
                    "Group Title: 1",
                    "Group Subtitle: 1",
                    "Assets/DarkGray.png",
                    "Group Description: Lorem ipsum dolor sit amet, consectetur adipiscing elit. Vivamus tempor scelerisque lorem in vehicula. Aliquam tincidunt, lacus ut sagittis tristique, turpis massa volutpat augue, eu rutrum ligula ante a ante");
            group1.Title = "Top Stories";
            group1.Subtitle = feedDataSource.Feeds[0].PubDate.ToString();
            group1.Description = feedDataSource.Feeds[0].Description;
            int i = 0;
            foreach (FeedItem item in feedDataSource.Feeds[0].Items)
            {
                i++;
                String img = "Assets/logo.png";
                if (item.ImageLink != null)
                    img = item.ImageLink.AbsoluteUri;
                var feedItem = new RSSDataItem("Group-1" + i.ToString(), item.Title, item.PubDate.ToString(), img, item.Description, item.ContentLink, group1);
                group1.Items.Add(feedItem);
                 GetBackgroundInfoForContent_Async(feedItem);
            }
            this.AllGroups.Add(group1);

        //    var group2 = new SampleDataGroup("Computing",
        //"Group Title: 2",
        //"Group Subtitle: 2",
        //"Assets/DarkGray.png",
        //"Group Description: Lorem ipsum dolor sit amet, consectetur adipiscing elit. Vivamus tempor scelerisque lorem in vehicula. Aliquam tincidunt, lacus ut sagittis tristique, turpis massa volutpat augue, eu rutrum ligula ante a ante");
        //    group2.Title = "Computing";
        //    group2.Subtitle = feedDataSource.Feeds[1].PubDate.ToString();
        //    group2.Description = feedDataSource.Feeds[1].Description;
        //    i = 0;
        //    foreach (FeedItem item in feedDataSource.Feeds[1].Items)
        //    {
        //        i++;
        //        String img = "Assets/logo.png";
        //        if (item.ImageLink != null)
        //            img = item.ImageLink.AbsoluteUri;

        //        var feedItem = new RSSDataItem("Computing" + i.ToString(), item.Title, item.PubDate.ToString(), img, HtmlUtilities.ConvertToText(item.Description), item.ContentLink, group2);
        //        group2.Items.Add(feedItem);
        //        GetBackgroundInfoForContent_Async(feedItem);
        //    }
        //    this.AllGroups.Add(group2);

        //    var group3 = new SampleDataGroup("Web",
        //"Group Title: 2",
        //"Group Subtitle: 2",
        //"Assets/DarkGray.png",
        //"Group Description: Lorem ipsum dolor sit amet, consectetur adipiscing elit. Vivamus tempor scelerisque lorem in vehicula. Aliquam tincidunt, lacus ut sagittis tristique, turpis massa volutpat augue, eu rutrum ligula ante a ante");
        //    group3.Title = "Web";
        //    group3.Subtitle = feedDataSource.Feeds[2].PubDate.ToString();
        //    group3.Description = feedDataSource.Feeds[2].Description;
        //    i = 0;
        //    foreach (FeedItem item in feedDataSource.Feeds[2].Items)
        //    {
        //        i++;
        //        String img = "Assets/logo.png";
        //        if (item.ImageLink != null)
        //            img = item.ImageLink.AbsoluteUri;

        //        var feedItem = new RSSDataItem("Web" + i.ToString(), item.Title, item.PubDate.ToString(), img, HtmlUtilities.ConvertToText(item.Description), item.ContentLink, group3);
        //        group3.Items.Add(feedItem);
        //        GetBackgroundInfoForContent_Async(feedItem);
        //    }
        //    this.AllGroups.Add(group3);

        //    var group4 = new SampleDataGroup("Communications",
        //"Group Title: 2",
        //"Group Subtitle: 2",
        //"Assets/DarkGray.png",
        //"Group Description: Lorem ipsum dolor sit amet, consectetur adipiscing elit. Vivamus tempor scelerisque lorem in vehicula. Aliquam tincidunt, lacus ut sagittis tristique, turpis massa volutpat augue, eu rutrum ligula ante a ante");
        //    group4.Title = "Communications";
        //    group4.Subtitle = feedDataSource.Feeds[3].PubDate.ToString();
        //    group4.Description = feedDataSource.Feeds[3].Description;
        //    i = 0;
        //    foreach (FeedItem item in feedDataSource.Feeds[3].Items)
        //    {
        //        i++;
        //        String img = "Assets/logo.png";
        //        if (item.ImageLink != null)
        //            img = item.ImageLink.AbsoluteUri;

        //        var feedItem = new RSSDataItem("Communications" + i.ToString(), item.Title, item.PubDate.ToString(), img, HtmlUtilities.ConvertToText(item.Description), item.ContentLink, group4);
        //        group4.Items.Add(feedItem);
        //        GetBackgroundInfoForContent_Async(feedItem);

        //    }
        //    this.AllGroups.Add(group4);

        //    var group5 = new SampleDataGroup("Energy",
        //"Group Title: 2",
        //"Group Subtitle: 2",
        //"Assets/DarkGray.png",
        //"Group Description: Lorem ipsum dolor sit amet, consectetur adipiscing elit. Vivamus tempor scelerisque lorem in vehicula. Aliquam tincidunt, lacus ut sagittis tristique, turpis massa volutpat augue, eu rutrum ligula ante a ante");
        //    group5.Title = "Energy";
        //    group5.Subtitle = feedDataSource.Feeds[4].PubDate.ToString();
        //    group5.Description = feedDataSource.Feeds[4].Description;
        //    i = 0;
        //    foreach (FeedItem item in feedDataSource.Feeds[4].Items)
        //    {
        //        i++;
        //        String img = "Assets/logo.png";
        //        if (item.ImageLink != null)
        //            img = item.ImageLink.AbsoluteUri;

        //        var feedItem = new RSSDataItem("Energy" + i.ToString(), item.Title, item.PubDate.ToString(), img, HtmlUtilities.ConvertToText(item.Description), item.ContentLink, group5);
        //        group5.Items.Add(feedItem);
        //        GetBackgroundInfoForContent_Async(feedItem);

        //    }
        //    this.AllGroups.Add(group5);

         //   var group6 = new SampleDataGroup("Biotech",
        //"Group Title: 2",
        //"Group Subtitle: 2",
        //"Assets/DarkGray.png",
        //"Group Description: Lorem ipsum dolor sit amet, consectetur adipiscing elit. Vivamus tempor scelerisque lorem in vehicula. Aliquam tincidunt, lacus ut sagittis tristique, turpis massa volutpat augue, eu rutrum ligula ante a ante");
        //    group6.Title = "Biotech";
        //    group6.Subtitle = feedDataSource.Feeds[5].PubDate.ToString();
        //    group6.Description = feedDataSource.Feeds[5].Description;
        //    i = 0;
        //    foreach (FeedItem item in feedDataSource.Feeds[5].Items)
        //    {
        //        i++;
        //        String img = "Assets/logo.png";
        //        if (item.ImageLink != null)
        //            img = item.ImageLink.AbsoluteUri;

        //        var feedItem = new RSSDataItem("Biotech" + i.ToString(), item.Title, item.PubDate.ToString(), img, HtmlUtilities.ConvertToText(item.Description), item.ContentLink, group6);
        //        group6.Items.Add(feedItem);
        //        GetBackgroundInfoForContent_Async(feedItem);

        //    }
        //    this.AllGroups.Add(group6);
        }
    }
}
